package cn.wolfcode.car.business.service.impl;

import cn.wolfcode.car.base.domain.User;
import cn.wolfcode.car.base.mapper.UserMapper;
import cn.wolfcode.car.business.domain.BpmnInfo;
import cn.wolfcode.car.business.domain.CarPackageAudit;
import cn.wolfcode.car.business.domain.Leave;
import cn.wolfcode.car.business.domain.ServiceItem;
import cn.wolfcode.car.business.mapper.BpmnInfoMapper;
import cn.wolfcode.car.business.mapper.LeaveMapper;
import cn.wolfcode.car.business.mapper.ServiceItemMapper;
import cn.wolfcode.car.business.query.LeaveQuery;
import cn.wolfcode.car.business.service.ILeaveService;
import cn.wolfcode.car.common.base.page.TablePageInfo;
import cn.wolfcode.car.common.exception.BusinessException;
import cn.wolfcode.car.shiro.ShiroUtils;
import com.github.pagehelper.PageHelper;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.image.ProcessDiagramGenerator;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.InputStream;
import java.security.PrivateKey;
import java.util.*;

@Service("leave")
@Transactional
public class LeaveServiceImpl implements ILeaveService {

    @Autowired
    private LeaveMapper leaveMapper;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private BpmnInfoMapper bpmnInfoMapper;
    @Autowired
    private ServiceItemMapper serviceItemMapper;
    @Autowired
    private TaskService taskService;
    @Autowired
    private UserMapper userMapper;

    @Override
    public TablePageInfo<Leave> query(LeaveQuery qo) {
        PageHelper.startPage(qo.getPageNum(), qo.getPageSize());
        return new TablePageInfo<Leave>(leaveMapper.selectForList(qo));
    }

    @Override
    public Leave get(Long id) {
        return leaveMapper.selectOne(id);
    }

    @Override
    @Transactional
    public void startAudit(Long id, Long bpmnInfoId,
                           Long director, Long finance,Leave leave) {

        Leave leave1 = new Leave();

        leave1.setAuditid(Integer.parseInt(director+""));
        leave1.setStarttime(leave.getStarttime());
        leave1.setEndtime(leave.getEndtime());
        leave1.setInfo(leave.getInfo());
        leave1.setName(ShiroUtils.getUser().getUserName());
        leave1.setReason(leave.getReason());
        leave1.setStatus("审核中");
        leaveMapper.insert(leave1);


        //开启流程实例之前查出来一个bpmnInfo信息
        BpmnInfo bpmnInfo = bpmnInfoMapper.selectByPrimaryKey(bpmnInfoId);
        // 设置流程变量
        Map<String,Object> map = new HashMap<>();
        map.put("manager",director);
        map.put("personnel",finance);
        //
        //开启流程实例
        //启动流程实例.获取流程实例id,获取到实例id后更新carpackageAudit对象的流程实例id
        ProcessInstance processInstance = runtimeService
                .startProcessInstanceByKey(bpmnInfo.getActProcessKey(), leave.getId() + "", map);

        leave1.setInstanceId(Long.parseLong(processInstance.getId()));
        leaveMapper.update(leave1);
/*        carPackageAudit.setInstanceId(processInstance.getId());
        carPackageAuditMapper.updateByPrimaryKey(carPackageAudit);*/

    }

    @Override
    @Transactional
    public void audit(Long id, Long auditStatus, String info) {
        //根据传过来的id查询出carpackage
        Leave leave = leaveMapper.selectOne(id);

        //完成任务 设置一个流程变量
        Map<String,Object> map = new HashMap<>();
        map.put("auditStatus",auditStatus);
        //根据流程实例id查询当前的当前的任务
        Task task = taskService.createTaskQuery().processInstanceId(leave.getInstanceId()+"").singleResult();
        //完成任务
        taskService.complete(task.getId(),map);
        if (auditStatus!=2){
            //审核拒绝
            //修改carPackageAudit 状态为审核拒绝 修改审核时间 修改审核审核人
            leave.setStatus("审核拒绝");
            leave.setInfo(leave.getInfo() +"<==> "+ShiroUtils.getUser().getUserName()+" 审批拒绝 ->意见: " + info );
        }else {
            //审核通过
            Task nextTask = taskService.createTaskQuery().processInstanceId(leave.getInstanceId()+"").singleResult();
            if (nextTask==null){
                //设置carPackageAudit状态为审核通过
                leave.setStatus("审核通过");
                //设置服务单项的审核状态为审核通过
                //修改审核人
                leaveMapper.setAuditorId(ShiroUtils.getUserId());
            }else {
                //更改审批人
                String assignee = nextTask.getAssignee();
                leave.setAuditid(Integer.parseInt(assignee));
            }
            leave.setInfo(leave.getInfo() +"<==> "+ShiroUtils.getUser().getUserName()+" 审批通过 ->意见: " + info );
        }
        leaveMapper.update(leave);

    }

    public List<User>getAllUser(){
        List<User> users = userMapper.selectAll();
        return users;
    }

    @Override
    public InputStream processImg(Long id) {
        //根据id查询出carPackageAudit的数据
        //判断是否在审核中的情况 如果审核中则需要高亮显示
        Leave leave = leaveMapper.selectOne(id);
        //判断状态
        List<String> list = null;
        Task task = taskService.createTaskQuery().processInstanceId(leave.getInstanceId().toString()).singleResult();
        String processDefinitionId = task.getProcessDefinitionId();
        if ("审核中".equals(leave.getStatus())){
            //查询出任务中的节点.进行高亮显示
            list = runtimeService.getActiveActivityIds(leave.getInstanceId().toString());

        }else {
            list = Collections.EMPTY_LIST;
        }
        //查询出bpmnInfo对象
        ProcessDiagramGenerator processDiagramGenerator = new DefaultProcessDiagramGenerator();
        InputStream inputStream = processDiagramGenerator.generateDiagram(repositoryService.getBpmnModel(processDefinitionId),
                list,
                Collections.emptyList(),
                "宋体",
                "宋体",
                "宋体");
        return inputStream;


    }

}
